import * as mime from 'mime';
import * as fs from 'fs';
import { Binary, ImageContent, ImageFormat } from 'easy-template-x';
import { Content } from './Content';
import * as http from 'http';
import * as https from 'https';

const _resolve = Symbol('_resolve');

const isHTTPS = (http: string) => {
    return /^https:\/\//ig.test(http);
}

const isURL = (str: string) => {
    return /^http(s)?:\/\//ig.test(str);
}

export class Image extends Content implements ImageContent {
    _type: 'image';
    source: Binary;
    altText?: string;
    format: ImageFormat;
    width: number;
    height: number;

    constructor(width?: number, height?: number, altText?: string) {
        super('image');
        this.width = width || 200;
        this.height = height || 200;
        this.altText = altText;
    }

    fetch(url: string) {
        let client: any = http;
        if (isHTTPS(url)) {
            client = https;
        }
        const self = this;
        Object.defineProperty(this, _resolve, {
            enumerable: false,
            value: new Promise((resolve) => {

                client.get(url, (res: http.IncomingMessage) => {
                    const { statusCode } = res;
                    const contentType = res.headers['content-type'];
                    let error;
                    if (statusCode !== 200) {
                        error = new Error('Request Failed.\n' +
                            `Status Code: ${statusCode}`);
                    }
                    if (error) {
                        resolve(false);
                        console.error(error.message);
                        // Consume response data to free up memory
                        res.resume();
                        return;
                    }

                    self.format = contentType.split(';')[0] as ImageFormat;
                    res.setEncoding("binary");
                    let rawData = '';
                    res.on('data', (chunk) => { 
                        rawData += chunk;
                     });
                    res.on('end', () => {
                        self.source = Buffer.from(rawData, 'binary');
                        resolve(true);
                        self.finish();
                    });
                }).on('error', (e: Error) => {
                    console.error(`Got error: ${e.message}`);
                    resolve(false);
                    self.finish();
                });
            })
        })
    }

    getResolve(): Promise<void> {
        if (this.isFinished()) {
            return super.getResolve();
        } else {
            return Object.getOwnPropertyDescriptor(this, _resolve).value;
        }
    }

    setSource(buffer: Binary, ext: string) {
        this.source = buffer;
        this.format = mime.getType(ext) as ImageFormat;
    }

    setPath(path: string) {
        if (isURL(path)) {
            this.unfinish();
            // 发送异步请求
            this.fetch(path);
        } else {
            this.source = fs.readFileSync(path);
            this.format = mime.getType(path) as ImageFormat;
        }
    }

}